﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using DevComponents.DotNetBar.Controls;
using AMS.Configuration;
using System.Windows.Forms;
using System.Data;
using System.ComponentModel;
using System.Collections;
using AMS.UI.Controls.Search;

/**
 * 支持的功能：
 * 1. 显示或不显示行号
 * 2. 显示或不显示CheckBox
 * 3. 行颜色间隔显示
 */
namespace AMS.UI.Controls
{
    [ToolboxBitmap(typeof(DataGridViewX))]
    public partial class AmsGridView : DevComponents.DotNetBar.Controls.DataGridViewX
    {
        public AmsGridView()
        {
        }

        #region 属性
        /// <summary>
        /// 是否在列头显示CheckBox，默认为true
        /// </summary>
        [DefaultValue(false)]
        public bool ShowCheckBoxes { get; set; }

        /// <summary>
        /// 是否在列头显示序号
        /// </summary>
        [DefaultValue(true)]
        public bool ShowRowNumbers { get; set; }
        private ListConfigInfo config;

        /// <summary>
        /// 配置信息
        /// </summary>
        [Browsable(false)]
        public ListConfigInfo Config
        {
            get { return config; }
        }

        private List<ColumnInfo> displayColumns;
        private const string CheckBoxColumnName = "_CHECKCOLUMN_";

        private object dataSource;
        /// <summary>
        /// 获取绑定的数据源
        /// </summary>
        public new object DataSource
        {
            get { return dataSource; }
        }

        private ISearchTool _selectionTool;
        /// <summary>
        /// 提供实时查找的接口对象
        /// </summary>
        [Browsable(false)]
        public ISearchTool SearchTool
        {
            get { return _selectionTool; }
            set
            {
                if (_selectionTool != null)
                {
                    _selectionTool.KeywordChanged -= new EventHandler<KeywordChangedEventArgs>(selectionTool_KeywordChanged);
                }

                _selectionTool = value;
                if (_selectionTool != null)
                {
                    _selectionTool.KeywordChanged += new EventHandler<KeywordChangedEventArgs>(selectionTool_KeywordChanged);
                }
            }
        }

        private int lastRowIndex = -1;
        #endregion

        #region 事件
        /// <summary>
        /// 当一行数据被按Enter的时候
        /// </summary>
        public event DataGridViewRowEventHandler RowEnterClicked;
        /// <summary>
        /// 当一行数据被按Enter的时候，触发事件
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnRowEnterClicked(DataGridViewRowEventArgs e)
        {
            if (RowEnterClicked != null)
            {
                RowEnterClicked(this, e);
            }
        }

        /// <summary>
        /// 当选中的行发生变化的时候
        /// </summary>
        public event EventHandler SelectedRowChanged;
        protected virtual void OnSelectedRowChanged()
        {
            if (SelectedRowChanged != null)
            {
                SelectedRowChanged(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// 数据源改变的时候触发的事件
        /// </summary>
        public new event EventHandler DataSourceChanged;
        /// <summary>
        /// 发起DataSourceChanged事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDataSourceChanged(EventArgs e)
        {
            if (this.DataSourceChanged != null)
            {
                this.DataSourceChanged(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// 当一行数据添加后触发的事件
        /// </summary>
        public event EventHandler<GridViewRowAddEventArgs> GridViewRowAdded;
        protected virtual void OnGridViewRowAdded(GridViewRowAddEventArgs e)
        {
            if (GridViewRowAdded != null)
            {
                GridViewRowAdded(this, e);

            }
        }
        #endregion

        #region 初始化
        /// <summary>
        /// 利用列信息初始化列表
        /// </summary>
        /// <param name="columnNamesFormat"></param>
        /// <param name="captionsFormat"></param>
        public void Init(string columnNamesFormat, string captionsFormat)
        {
            ListConfigInfo config = new ListConfigInfo();
            config.ColumnFormat = columnNamesFormat;
            config.CaptionFormat = captionsFormat;
            Init(config);
        }

        /// <summary>
        /// 利用指定的行和列的数据初始化
        /// </summary>
        /// <param name="columns"></param>
        /// <param name="captions"></param>
        public void Init(string[] columns, string[] captions)
        {
            int index;
            Columns.Clear();
            if (ShowCheckBoxes)
            {
                CreateCheckBoxColumn();
            }

            Reset();
            for (int i = 0; i < columns.Length; i++)
            {
                if (string.IsNullOrEmpty(columns[i]))
                {
                    continue;
                }

                index = Columns.Add(columns[i], captions[i]);
                Columns[index].DataPropertyName = columns[i];
            }
        }

        /// <summary>
        /// 利用ListConfigInfo列数据初始化
        /// </summary>
        /// <param name="config"></param>
        public void Init(ListConfigInfo config)
        {
            int index;
            Columns.Clear();
            if (ShowCheckBoxes)
            {
                CreateCheckBoxColumn();
            }

            List<ColumnInfo> columns = config.ParseDisplayColumns();
            foreach (ColumnInfo item in columns)
            {
                index = Columns.Add(item.Name, item.Caption);
                if (!(item is CompoundColumnInfo))
                {
                    Columns[index].DataPropertyName = item.Name;
                }

                Columns[index].ReadOnly = true;
                if (item.Width > 0)
                {
                    Columns[index].Width = item.Width;
                }

                if (item.HAlign != HorizenAlignment.UnDefined)
                {
                    DataGridViewContentAlignment align = DataGridViewContentAlignment.MiddleLeft;
                    switch (item.HAlign)
                    {
                        case HorizenAlignment.Left:
                            align = DataGridViewContentAlignment.MiddleLeft;
                            break;
                        case HorizenAlignment.Middle:
                            align = DataGridViewContentAlignment.MiddleCenter;
                            Columns[index].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
                            break;
                        case HorizenAlignment.Right:
                            align = DataGridViewContentAlignment.MiddleRight;
                            break;
                        default:
                            throw new NotImplementedException("未指定对对齐方式的实现");
                    }

                    Columns[index].DefaultCellStyle.Alignment = align;
                }
            }

            this.config = config;
            displayColumns = columns;
            Reset();
        }

        private void CreateCheckBoxColumn()
        {
            DataGridViewCheckBoxColumn chkColumn = new DataGridViewCheckBoxColumn();
            chkColumn.Name = CheckBoxColumnName;
            chkColumn.DataPropertyName = CheckBoxColumnName;
            chkColumn.HeaderText = "";
            chkColumn.Width = 20;
            chkColumn.Frozen = true;
            Columns.Add(chkColumn);
        }

        private void Reset()
        {
            lastRowIndex = -1;
        }
        #endregion

        #region 选择
        /// <summary>
        /// 
        /// </summary>
        public void CheckAll()
        {
            SetAllCheckStatus(true);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="isChecked"></param>
        public void CheckAll(bool isChecked)
        {
            SetAllCheckStatus(isChecked);
        }
        /// <summary>
        /// 
        /// </summary>
        public void UnCheckAll()
        {
            SetAllCheckStatus(false);
        }
        /// <summary>
        /// 
        /// </summary>
        public void CheckExcluted()
        {
            if (!ShowCheckBoxes)
            {
                return;
            }
        }

        private void SetAllCheckStatus(bool status)
        {
            if (!ShowCheckBoxes)
            {
                return;
            }

            int columnIndex = Columns[CheckBoxColumnName].Index;
            object ostatus = (object)status;
            foreach (DataGridViewRow row in Rows)
            {
                row.Cells[columnIndex].Value = ostatus;
            }
        }

        /// <summary>
        /// 获取选中的行序号
        /// </summary>
        /// <returns></returns>
        public int[] GetCheckedIndices()
        {
            if (!ShowCheckBoxes)
            {
                return null;
            }

            int columnIndex = Columns[CheckBoxColumnName].Index;
            List<int> indices = new List<int>();
            foreach (DataGridViewRow row in Rows)
            {
                if (row.Cells[columnIndex].Value != null
                    && row.Cells[columnIndex].Value != DBNull.Value
                    && (bool)row.Cells[columnIndex].Value)
                {
                    indices.Add(row.Index);
                }
            }

            return indices.ToArray();
        }

        /// <summary>
        /// 获取选中的行
        /// </summary>
        /// <returns></returns>
        public DataGridViewRow[] GetCheckedRows()
        {
            if (!ShowCheckBoxes)
            {
                return null;
            }

            int columnIndex = Columns[CheckBoxColumnName].Index;
            List<DataGridViewRow> checkedRows = new List<DataGridViewRow>();
            foreach (DataGridViewRow row in Rows)
            {
                if ((bool)row.Cells[columnIndex].Value)
                {
                    checkedRows.Add(row);
                }
            }

            return checkedRows.ToArray();
        }

        /// <summary>
        /// 获取选中的行
        /// </summary>
        /// <returns></returns>
        public int[] GetCheckedDataRowIndices()
        {
            return GridViewRowIndicesToDataRowIndices(GetCheckedIndices());
        }

        /// <summary>
        /// 将列表的行索引转换成绑定的数据的索引
        /// </summary>
        /// <param name="gridViewRowIndices"></param>
        /// <returns></returns>
        public int[] GridViewRowIndicesToDataRowIndices(int[] gridViewRowIndices)
        {
            if (gridViewRowIndices == null || gridViewRowIndices.Length == 0)
            {
                return null;
            }

            List<int> dataRowIndices = new List<int>();
            foreach (int rowIndex in gridViewRowIndices)
            {
                dataRowIndices.Add((int)Rows[rowIndex].Tag);
            }

            return dataRowIndices.ToArray();
        }

        /// <summary>
        /// 获取选中的行的数据在转换成数据源（DataSource）中的行索引
        /// </summary>
        /// <returns></returns>
        public int GetSelectedRowDataIndex()
        {
            if (null == SelectedRows || SelectedRows.Count == 0)
            {
                return -1;
            }

            return (null == SelectedRows[0].Tag) ? -1 : (int)SelectedRows[0].Tag;
        }

        /// <summary>
        /// 将一行的选中状态在选中和不选中中切换
        /// </summary>
        /// <param name="rowIndex"></param>
        public void ToggleRowCheckStatus(int rowIndex)
        {
            if (!ShowCheckBoxes)
            {
                return;
            }

            if (rowIndex < 0 || rowIndex >= Rows.Count)
            {
                throw new ArgumentOutOfRangeException("rowIndex");
            }

            object ovalue = Rows[rowIndex].Cells[CheckBoxColumnName].Value;
            bool isChecked = false;
            if (ovalue != null && ovalue != DBNull.Value)
            {
                isChecked = (bool)ovalue;
            }

            Rows[rowIndex].Cells[CheckBoxColumnName].Value = (object)(!isChecked);
        }
        #endregion

        #region 数据绑定
        /// <summary>
        /// 绑定非DataTable类型的数据，但数据类型必需是IEnumerable
        /// </summary>
        /// <param name="dataSource"></param>
        public void DataBind(object dataSource)
        {
            if (dataSource == null)
            {
                Rows.Clear();
                this.dataSource = dataSource;
                OnDataSourceChanged(EventArgs.Empty);
                return;
            }

            lastRowIndex = -1;
            if (dataSource is DataTable)
            {
                DataBindDataTable(dataSource as DataTable);
            }
            else if (dataSource is IEnumerable)
            {
                DataBindEnuerable(dataSource as IEnumerable);
            }
            else
            {
                throw new NotSupportedException("数据必需是DataTable或实现了IEnumable接口");
            }

            OnDataSourceChanged(EventArgs.Empty);
        }

        /// <summary>
        /// 绑定类型为DataTable的数据
        /// </summary>
        /// <param name="dataSource"></param>
        private void DataBindDataTable(DataTable dataSource)
        {
            this.dataSource = dataSource;
            Rows.Clear();
            if (dataSource == null || dataSource.Rows.Count == 0)
            {
                return;
            }

            // 将DataTable的列名与列索引建立起映射关系，避免使用列名去索引
            Dictionary<string, int> dataColumnIndexMapping = new Dictionary<string, int>();
            for (int i = 0; i < dataSource.Columns.Count; i++)
            {
                dataColumnIndexMapping.Add(dataSource.Columns[i].ColumnName, i);
            }

            // 建立起显示的列名和列信息的映射
            Dictionary<string, ColumnInfo> displayColumnInfoMapping = GetDisplayColumnMapping();
            for (int i = 0; i < dataSource.Rows.Count; i++)
            {
                int newRowIndex = AddDataRowToGridViewRow(dataSource.Rows[i], dataColumnIndexMapping, displayColumnInfoMapping);
                OnGridViewRowAdded(new GridViewRowAddEventArgs(Rows[newRowIndex], dataSource.Rows[i]));
            }

            OnDataSourceChanged(EventArgs.Empty);
        }

        private void DataBindEnuerable(IEnumerable dataSource)
        {
            this.dataSource = dataSource;
            Rows.Clear();
            if (dataSource == null)
            {
                return;
            }

            PropertyDescriptorCollection properties = ListBindingHelper.GetListItemProperties(dataSource);
            Dictionary<string, PropertyDescriptor> propertyNameToProperty = new Dictionary<string, PropertyDescriptor>();
            for (int i = 0; i < properties.Count; i++)
            {
                propertyNameToProperty.Add(properties[i].Name, properties[i]);
            }

            IEnumerable ie = (IEnumerable)dataSource;
            IEnumerator enumerator = ie.GetEnumerator();
            int index = -1;
            Dictionary<string, ColumnInfo> displayColumnNameToColumnInfo = GetDisplayColumnMapping();
            while (enumerator.MoveNext())
            {
                index++;
                int newRowIndex = AddObjectToGridViewRow(index, enumerator.Current, propertyNameToProperty, displayColumnNameToColumnInfo);
                OnGridViewRowAdded(new GridViewRowAddEventArgs(Rows[newRowIndex], enumerator.Current));
            }
        }

        private Dictionary<string, ColumnInfo> GetDisplayColumnMapping()
        {
            Dictionary<string, ColumnInfo> displayColumnNameToColumnInfo = new Dictionary<string, ColumnInfo>();
            for (int i = 0; i < displayColumns.Count; i++)
            {
                displayColumnNameToColumnInfo.Add(displayColumns[i].Name, displayColumns[i]);
            }
            return displayColumnNameToColumnInfo;
        }

        /// <summary>
        /// 将DataTable的和一行数据添加到GridView中
        /// </summary>
        /// <param name="dataRow">数据行</param>
        /// <param name="columnNameToIndex">数据源列名到列索引的映射关系</param>
        /// <param name="displayColumnNameToColumnInfo">GridView的列名与列信息的映射关系</param>
        private int AddDataRowToGridViewRow(DataRow dataRow, Dictionary<string, int> columnNameToIndex, Dictionary<string, ColumnInfo> displayColumnNameToColumnInfo)
        {
            int rowIndex = Rows.Add();
            UpdateDataRowToGridViewRow(rowIndex, dataRow, columnNameToIndex, displayColumnNameToColumnInfo);
            return rowIndex;
        }

        /// <summary>
        /// 将DataTable的和一行数据添加到GridView中
        /// </summary>
        /// <param name="gridRowIndex">当前行</param>
        /// <param name="dataRow">数据行</param>
        /// <param name="columnNameToIndex">数据源列名到列索引的映射关系</param>
        /// <param name="displayColumnNameToColumnInfo">GridView的列名与列信息的映射关系</param>
        private void UpdateDataRowToGridViewRow(int gridRowIndex, DataRow dataRow, Dictionary<string, int> columnNameToIndex, Dictionary<string, ColumnInfo> displayColumnNameToColumnInfo)
        {
            DataGridViewRow row = Rows[gridRowIndex];
            row.Tag = (object)row.Index;
            for (int i = 0; i < Columns.Count; i++)
            {
                DataGridViewColumn column = Columns[i];
                if (column.Name == CheckBoxColumnName)
                {
                    continue;
                }

                if (!displayColumnNameToColumnInfo.ContainsKey(column.Name))
                {
                    continue;
                }

                if (displayColumnNameToColumnInfo[column.Name] is CompoundColumnInfo)
                {
                    // 组合列
                    CompoundColumnInfo compoundColumn = displayColumnNameToColumnInfo[column.Name] as CompoundColumnInfo;
                    if (compoundColumn.Columns.Length == 0)
                    {
                        row.Cells[i].Value = compoundColumn.Format;
                        continue;
                    }

                    // 获取每个子列的值，然后使用string.Format()构造成出新的组合值
                    string[] subValues = new string[compoundColumn.Columns.Length];
                    for (int j = 0; j < compoundColumn.Columns.Length; j++)
                    {
                        ColumnInfo subColumn = compoundColumn.Columns[j];
                        int columnIndex = columnNameToIndex[subColumn.Name];
                        if (subColumn.DictKey > 0)
                        {
                            subValues[j] = GetDictValueBySubKey(subColumn.DictKey, dataRow[columnIndex]);
                        }
                        else
                        {
                            subValues[j] = Convert.ToString(dataRow[columnIndex]);
                        }
                    }

                    row.Cells[i].Value = string.Format(compoundColumn.Format, subValues);
                }
                else
                {
                    // 简单列
                    int columnIndex = columnNameToIndex[column.Name];
                    if (dataRow[columnIndex] == null || dataRow[columnIndex] == DBNull.Value)
                    {
                        row.Cells[i].Value = null;
                        continue;
                    }

                    // 处理是否字典列
                    if (displayColumnNameToColumnInfo[column.DataPropertyName].DictKey > 0)
                    {
                        row.Cells[i].Value = GetDictValueBySubKey(displayColumnNameToColumnInfo[column.DataPropertyName].DictKey, dataRow[columnIndex]);
                    }
                    else
                    {
                        row.Cells[i].Value = dataRow[columnIndex];
                    }
                }
            }
        }

        /// <summary>
        /// 添加object的值到一行数据
        /// </summary>
        /// <param name="dataRowIndex"></param>
        /// <param name="rawData"></param>
        /// <param name="nameToProperty"></param>
        /// <param name="displayColumnNameToColumnInfo"></param>
        private int AddObjectToGridViewRow(int dataRowIndex, object rawData, Dictionary<string, PropertyDescriptor> nameToProperty, Dictionary<string, ColumnInfo> displayColumnNameToColumnInfo)
        {
            int rowIndex = Rows.Add();
            UpdateObjectToGridViewRow(rowIndex, dataRowIndex, rawData, nameToProperty, displayColumnNameToColumnInfo);
            return rowIndex;
        }

        /// <summary>
        /// 更新object的值到一行数据
        /// </summary>
        /// <param name="gridRowIndex"></param>
        /// <param name="dataRowIndex"></param>
        /// <param name="rawData"></param>
        /// <param name="nameToProperty"></param>
        /// <param name="displayColumnNameToColumnInfo"></param>
        private void UpdateObjectToGridViewRow(int gridRowIndex, int dataRowIndex, object rawData, Dictionary<string, PropertyDescriptor> nameToProperty, Dictionary<string, ColumnInfo> displayColumnNameToColumnInfo)
        {
            DataGridViewRow row = Rows[gridRowIndex];
            row.Tag = (object)dataRowIndex;
            for (int i = 0; i < Columns.Count; i++)
            {
                DataGridViewColumn column = Columns[i];
                if (column.Name == CheckBoxColumnName)
                {
                    continue;
                }

                if (!displayColumnNameToColumnInfo.ContainsKey(column.Name))
                {
                    continue;
                }

                if (displayColumnNameToColumnInfo[column.Name] is CompoundColumnInfo)
                {
                    // 组合列
                    CompoundColumnInfo compoundColumn = displayColumnNameToColumnInfo[column.Name] as CompoundColumnInfo;
                    if (compoundColumn.Columns.Length == 0)
                    {
                        row.Cells[i].Value = compoundColumn.Format;
                        continue;
                    }

                    // 获取每个子列的值，然后使用string.Format()构造成出新的组合值
                    string[] subValues = new string[compoundColumn.Columns.Length];
                    for (int j = 0; j < compoundColumn.Columns.Length; j++)
                    {
                        ColumnInfo subColumn = compoundColumn.Columns[j];
                        PropertyDescriptor property = nameToProperty[subColumn.Name];
                        if (subColumn.DictKey > 0)
                        {
                            subValues[j] = GetDictValueBySubKey(subColumn.DictKey, property.GetValue(rawData));
                        }
                        else
                        {
                            subValues[j] = Convert.ToString(property.GetValue(rawData));
                        }
                    }

                    row.Cells[i].Value = string.Format(compoundColumn.Format, subValues);
                }
                else
                {
                    // 简单列
                    if (!nameToProperty.ContainsKey(column.Name))
                    {
                        continue;
                    }

                    PropertyDescriptor property = nameToProperty[column.Name];
                    object ovalue = property.GetValue(rawData);
                    if (ovalue == null || ovalue == DBNull.Value)
                    {
                        row.Cells[i].Value = null;
                        continue;
                    }

                    // 处理是否字典列
                    if (displayColumnNameToColumnInfo[column.DataPropertyName].DictKey > 0)
                    {
                        row.Cells[i].Value = GetDictValueBySubKey(displayColumnNameToColumnInfo[column.DataPropertyName].DictKey, ovalue);
                    }
                    else
                    {
                        row.Cells[i].Value = ovalue;
                    }
                }
            }
        }

        /// <summary>
        /// 获取字典的值
        /// </summary>
        /// <param name="dictKey"></param>
        /// <param name="subKeyValue"></param>
        /// <returns></returns>
        private string GetDictValueBySubKey(int dictKey, object subKeyValue)
        {
            if (subKeyValue == null || subKeyValue == DBNull.Value)
            {
                return string.Empty;
            }
            else
            {
                string dictSubKey;
                // 处理BOOL类型
                if (subKeyValue.GetType() == typeof(bool) || subKeyValue == typeof(bool?))
                {
                    dictSubKey = ((bool)subKeyValue) ? "1" : "0";
                }
                else
                {
                    dictSubKey = Convert.ToString(subKeyValue);
                }

                return Dict.Instance.GetDictValueWithNoException(dictKey, dictSubKey);
            }
        }
        #endregion

        #region 绘图
        protected override void OnRowPrePaint(DataGridViewRowPrePaintEventArgs e)
        {
            e.PaintParts = e.PaintParts ^ DataGridViewPaintParts.Focus;
            base.OnRowPrePaint(e);
        }

        protected override void OnRowPostPaint(DataGridViewRowPostPaintEventArgs e)
        {
            base.OnRowPostPaint(e);
            if (ShowRowNumbers)
            {
                int index = e.RowIndex + 1;
                Rectangle rc = new Rectangle(
                    e.RowBounds.Location.X,
                    e.RowBounds.Location.Y,
                    RowHeadersWidth - 4,
                    e.RowBounds.Height);

                TextRenderer.DrawText(e.Graphics, index.ToString(), RowHeadersDefaultCellStyle.Font, rc, RowHeadersDefaultCellStyle.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.Right);
            }
        }
        #endregion

        #region 查找
        void selectionTool_KeywordChanged(object sender, KeywordChangedEventArgs e)
        {
            DoSearch(e.Keyword, e.First);
        }

        /// <summary>
        /// 查找并定位列表中的某列
        /// </summary>
        /// <param name="keyword"></param>
        /// <param name="first"></param>
        public void DoSearch(string keyword, bool first)
        {
            if (Columns.Count == 0 || Rows.Count == 0)
            {
                return;
            }

            if (string.IsNullOrEmpty(keyword))
            {
                return;
            }

            int startIndex = 0;
            if (SelectedRows != null)
            {
                startIndex = SelectedRows[0].Index;
            }

            bool found = false;
            int index = startIndex;
            if (first)
            {
                index--;
            }

            while ((++index) < Rows.Count)
            {
                int cellIndex = IndexKeywordInRow(Rows[index], keyword);
                if (cellIndex >= 0)
                {
                    Rows[index].Cells[cellIndex].Selected = true;
                    CurrentCell = Rows[index].Cells[cellIndex];
                    found = true;
                    break;
                }
            }

            if (found)
            {
                return;
            }

            index = -1;
            while ((++index) < Rows.Count)
            {
                int cellIndex = IndexKeywordInRow(Rows[index], keyword);
                if (cellIndex >= 0)
                {
                    Rows[index].Cells[cellIndex].Selected = true;
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                System.Media.SystemSounds.Beep.Play();
            }
        }

        private int IndexKeywordInRow(DataGridViewRow row, string keyword)
        {
            for (int i = 0; i < row.Cells.Count; i++)
            {
                if (row.Cells[i].Value != null && row.Cells[i].Value != DBNull.Value && row.Cells[i].Value is string)
                {
                    string value = Convert.ToString(row.Cells[i].Value);
                    if (!string.IsNullOrEmpty(value) && value.IndexOf(keyword, StringComparison.CurrentCultureIgnoreCase) >= 0)
                    {
                        return i;
                    }
                }
            }

            return -1;
        }
        #endregion

        #region 事件
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (Rows.Count == 0 || SelectedRows.Count == 0)
            {
                return base.ProcessCmdKey(ref msg, keyData);
            }

            int rowIndex = SelectedRows[0].Index;
            int columnIndex = 0;
            if (CurrentCell != null)
            {
                columnIndex = CurrentCell.ColumnIndex;
            }

            switch (keyData)
            {
                case Keys.Down:
                    if (rowIndex < Rows.Count - 1)
                    {
                        Rows[rowIndex + 1].Selected = true;
                        CurrentCell = Rows[rowIndex + 1].Cells[columnIndex];
                    }

                    return true;

                case Keys.Up:
                    if (rowIndex > 0)
                    {
                        Rows[rowIndex - 1].Selected = true;
                        CurrentCell = Rows[rowIndex - 1].Cells[columnIndex];
                    }

                    return true;

                case Keys.Enter:
                    DataGridViewRowEventArgs e = new DataGridViewRowEventArgs(SelectedRows[0]);
                    OnRowEnterClicked(e);
                    return true;

                case Keys.Home:
                    if (Rows.Count > 0)
                    {
                        CurrentCell = Rows[0].Cells[columnIndex];
                    }
                    return true;

                case Keys.End:
                    if (Rows.Count > 0)
                    {
                        CurrentCell = Rows[Rows.Count - 1].Cells[columnIndex];
                    }
                    return true;
            }

            return base.ProcessCmdKey(ref msg, keyData);
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            if (!e.Control && !e.Alt && e.KeyCode == Keys.F3)
            {
                if (SearchTool != null)
                {
                    if (string.IsNullOrEmpty(SearchTool.Keyword))
                    {
                        SearchTool.ShowTo(this);
                    }
                    else
                    {
                        DoSearch(SearchTool.Keyword, false);
                    }
                }
            }
            else if (e.Control && !e.Alt && e.KeyCode == Keys.F)
            {
                SearchTool.ShowTo(this);
            }
            else if (e.Control && e.KeyCode == Keys.C)
            {
                // 拷贝
                if (Rows.Count == 0)
                {
                    return;
                }

                if (SelectedRows == null || SelectedRows.Count == 0)
                {
                    return;
                }

                StringBuilder copyContent = new StringBuilder();
                foreach (DataGridViewRow row in SelectedRows)
                {
                    foreach (DataGridViewCell cell in row.Cells)
                    {
                        copyContent.Append(Convert.ToString(cell.Value));
                        copyContent.Append("\t");
                    }

                    copyContent.AppendLine();
                }

                copyContent.AppendLine();
                Clipboard.SetText(copyContent.ToString());
            }
            else if (e.KeyCode == Keys.Space)
            {
                if (CurrentCell != null)
                {
                    ToggleRowCheckStatus(CurrentCell.RowIndex);
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnCurrentCellChanged(EventArgs e)
        {
            base.OnCurrentCellChanged(e);
            if (CurrentCell != null && CurrentCell.RowIndex != lastRowIndex)
            {
                lastRowIndex = CurrentCell.RowIndex;
                OnSelectedRowChanged();
            }
        }

        private void AmsGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            // TODO: DELETE THE METHOD
        }

        /// <summary>
        /// 当数据改变时，处理值改变信息
        /// </summary>
        /// <param name="rowIndex"></param>
        /// <param name="columnIndex"></param>
        private void ProcessCellValueChanged(int rowIndex, int columnIndex)
        {
            if (config != null && Rows[rowIndex].Cells[columnIndex].Value != null && Rows[rowIndex].Cells[columnIndex].Value != DBNull.Value)
            {
                int displayColumnIndex = columnIndex;
                if (ShowCheckBoxes)
                {
                    displayColumnIndex--;
                }

                if (displayColumns[displayColumnIndex].DictKey != 0)
                {
                    try
                    {
                        string subKey = Convert.ToString(Rows[rowIndex].Cells[columnIndex].Value);
                        Rows[rowIndex].Cells[columnIndex].Value = Dict.Instance.GetDictValue(displayColumns[displayColumnIndex].DictKey, subKey);
                    }
                    catch (Exception ex)
                    {
                        // 不让抛出异常
                        // TODO: 测试的时候，抛出异常
                        throw ex;
                    }
                }
            }
        }
        #endregion

        #region 行操作
        /// <summary>
        /// 更新选中的行数据
        /// </summary>
        public void UpdateSelectedRows()
        {
            if (SelectedRows == null || SelectedRows.Count == 0)
            {
                return;
            }

            List<int> indices = new List<int>();
            foreach (DataGridViewRow row in SelectedRows)
            {
                indices.Add((int)row.Tag);
            }

            UpdateRowsInternal(indices.ToArray());
        }

        /// <summary>
        /// 更新给定的行
        /// </summary>
        /// <param name="rowIndex"></param>
        public void UpdateRow(int rowIndex)
        {
            UpdateRowsInternal(new int[] { rowIndex });
        }

        /// <summary>
        /// 更新行信息
        /// </summary>
        /// <param name="rowIndices"></param>
        private void UpdateRowsInternal(int[] rowIndices)
        {
            Dictionary<string, ColumnInfo> displayColumnInfoMapping = GetDisplayColumnMapping();

            if (dataSource is DataTable)
            {
                DataTable table = dataSource as DataTable;
                Dictionary<string, int> dataColumnIndexMapping = new Dictionary<string, int>();
                for (int i = 0; i < table.Columns.Count; i++)
                {
                    dataColumnIndexMapping.Add(table.Columns[i].ColumnName, i);
                }

                foreach (int rowIndex in rowIndices)
                {
                    int dataIndex = (int)Rows[rowIndex].Tag;
                    UpdateDataRowToGridViewRow(rowIndex, table.Rows[dataIndex], dataColumnIndexMapping, displayColumnInfoMapping);
                }
            }
            else
            {
                PropertyDescriptorCollection properties = ListBindingHelper.GetListItemProperties(dataSource);
                Dictionary<string, PropertyDescriptor> propertyNameToProperty = new Dictionary<string, PropertyDescriptor>();
                for (int i = 0; i < properties.Count; i++)
                {
                    propertyNameToProperty.Add(properties[i].Name, properties[i]);
                }

                IEnumerable ie = (IEnumerable)dataSource;
                IEnumerator enumerator = ie.GetEnumerator();
                int index = -1;

                Array.Sort<int>(rowIndices);
                foreach (int rowIndex in rowIndices)
                {
                    int dataIndex = (int)Rows[rowIndex].Tag;
                    while (index < dataIndex && enumerator.MoveNext())
                    {
                        index++;
                    }

                    UpdateObjectToGridViewRow(rowIndex, index, enumerator.Current, propertyNameToProperty, displayColumnInfoMapping);
                }
            }
        }
        #endregion
    }
}
